using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace SolarWinds.Shapes
{
    public class GridShape : Shape
    {
        private VertexBuffer mVertexBuffer;
        private VertexDeclaration mVertexDeclaration;
        private IndexBuffer mIndexBuffer;
        private BasicEffect mBasicEffect;

        private const int cSubdivisionsU = 10;
        private const int cSubdivisionsV = 10;

        public Color LineColor = Color.CornflowerBlue;

        public GridShape(Game game) : base(game)
        {
        }

        public override void  Draw(GameTime gameTime)
        {
 	        base.Draw(gameTime);
    
            GraphicsDevice device = Game.GraphicsDevice;

            device.Vertices[0].SetSource(mVertexBuffer, 0, VertexPositionColor.SizeInBytes);
            device.VertexDeclaration = mVertexDeclaration;
            device.Indices = mIndexBuffer;

            mBasicEffect.World = World;
            mBasicEffect.View = View;
            mBasicEffect.Projection = Projection;
            mBasicEffect.DiffuseColor = LineColor.ToVector3();
            mBasicEffect.CommitChanges();

            mBasicEffect.Begin();
            foreach (EffectPass pass in mBasicEffect.CurrentTechnique.Passes)
            {
                pass.Begin();
                device.DrawPrimitives(PrimitiveType.LineList, 0, cSubdivisionsU+cSubdivisionsV);
                pass.End();
            }
            mBasicEffect.End();
        }

        protected override BoundingSphere UpdateBoundingSphere()
        {
            return new BoundingSphere(Vector3.Zero, Vector2.One.Length());
        }

        protected override BoundingBox UpdateBoundingBox()
        {
            return new BoundingBox(new Vector3(-1.0f, -float.Epsilon, -1.0f), new Vector3(1.0f, float.Epsilon, 1.0f));
        }

        protected override void LoadContent()
        {
            GraphicsDevice device = Game.GraphicsDevice;

            // Fill vertex buffer
            int vertexCount = 2 * cSubdivisionsU + 2 * cSubdivisionsV;
            mVertexBuffer = new VertexBuffer(device, typeof(VertexPositionColor), vertexCount, BufferUsage.WriteOnly);
            var vertexData = new VertexPositionColor[vertexCount];

            //var pos = new Vector3[mVertexCount];

            vertexCount = 0;
            float sample;
            for (int u = 0; u < cSubdivisionsU; ++u)
            {
                sample = (2.0f * ((float)u / (cSubdivisionsU - 1))) - 1.0f;

                vertexData[vertexCount].Position = new Vector3(sample, 0.0f, 1.0f);
                vertexData[vertexCount].Color = Color.Gray;
                ++vertexCount;

                vertexData[vertexCount].Position = new Vector3(sample, 0.0f, -1.0f);
                vertexData[vertexCount].Color = Color.Gray;
                ++vertexCount;
            }

            for (int v = 0; v < cSubdivisionsV; ++v)
            {
                sample = (2.0f * ((float)v / (cSubdivisionsV - 1))) - 1.0f;

                vertexData[vertexCount].Position = new Vector3(1.0f, 0.0f, sample);
                vertexData[vertexCount].Color = Color.Gray;
                ++vertexCount;

                vertexData[vertexCount].Position = new Vector3(-1.0f, 0.0f, sample);
                vertexData[vertexCount].Color = Color.Gray;
                ++vertexCount;
            }

            mVertexBuffer.SetData(vertexData);
            mVertexDeclaration = new VertexDeclaration(device, VertexPositionColor.VertexElements);
            
            mBasicEffect = new BasicEffect(device, null);
            //mBasicEffect.EnableDefaultLighting();

            base.LoadContent();
        }

        protected override void UnloadContent()
        {
            base.UnloadContent();

            if (mVertexBuffer != null)
            {
                mVertexBuffer.Dispose();
                mVertexBuffer = null;
            }

            if (mVertexDeclaration != null)
            {
                mVertexDeclaration.Dispose();
                mVertexDeclaration = null;
            }

            if (mIndexBuffer != null)
            {
                mIndexBuffer.Dispose();
                mIndexBuffer = null;
            }

            if (mBasicEffect != null)
            {
                mBasicEffect.Dispose();
                mBasicEffect = null;
            }
        }

        /* Can be used in terrain renderer but is not working correctly
        protected override void FillBuffers()
        {
            GraphicsDevice device = DeepSpaceGame.GraphicsDevice;

            // Fill vertex buffer
            mVertexBuffer = new VertexBuffer(device, typeof(VertexPositionColor), cSubdivisionsU*cSubdivisionsV, ResourceUsage.WriteOnly);
            VertexPositionColor[] vertexData = new VertexPositionColor[cSubdivisionsU*cSubdivisionsV];

            mVertexCount = 0;
            for (int u = 0; u < cSubdivisionsU; ++u)
                for (int v = 0; v < cSubdivisionsV; ++v)
                {
                    vertexData[mVertexCount].Position = new Vector3((float)u / (cSubdivisionsU - 1), 
                                                    (float)v / (cSubdivisionsV - 1), 
                                                    0.0f);
                    vertexData[mVertexCount].Color = Color.Gray;
                    ++mVertexCount;
                }

            mVertexBuffer.SetData<VertexPositionColor>(vertexData);
            mVertexDeclaration = new VertexDeclaration(device, VertexPositionColor.VertexElements);

            // Fill index buffer
            mPatchCount = (cSubdivisionsU - 1) * (cSubdivisionsV - 1);
            
            mIndexBuffer = new IndexBuffer(device, typeof(int), mPatchCount * 4,
                                           ResourceUsage.Dynamic | ResourceUsage.WriteOnly,
                                           ResourceManagementMode.Manual);

            int[] indexData = new int[mPatchCount*4]; // each patch has 4 vertices (remember we render as trianglestrip)
            
            // for each patch ...
            int pi = 0;
            for (int i = 0; i < mPatchCount; ++i) 
            {
                //... fill indexData buffer
                indexData[pi++] = i;
                indexData[pi++] = i + 1;
                indexData[pi++] = i + 1 + cSubdivisionsU;
                indexData[pi++] = i;
            }

            mIndexBuffer.SetData<int>(indexData);
        }*/
    }
}